#include <Arduino.h>
#include <ESP8266WebServer.h> 
#include <ESP8266WiFiMulti.h>
#include <ESP8266WiFi.h>
#include <FastLED.h>

#define lightNum  60  // 灯珠数目
#define dataPin 5    //数字信号引脚
#define ledType WS2812B   // 灯带信号
#define COLOR_ORDER GRB  // RGB

uint8_t prefix[] = { 'A', 'd', 'a' };
uint8_t hi, lo, chk, i;

CRGB led[lightNum]; // 灯带数组

// 设置变量 用于判断是否是流光溢彩模式还是 其他的模式

int mode = 3; // 默认就是灯光控制   0  ， 1  色彩模式  2 流光溢彩

const char* wifiName = "ESP8266";  // esp8266Wifi 名称
const char* wifiPassword = "123456789";  // esp8266 wifi密码


// web服务配置 
ESP8266WebServer esp8266_server(80); 
ESP8266WiFiMulti wifiMulti;
IPAddress local_IP(192, 168, 4,10 );
IPAddress gateway(192 , 168 ,4,1);
IPAddress subnet(255, 255, 255, 0);

// led灯的亮度
uint8_t lightNess = 128;


// led 颜色
int r = 255; 
int g = 123;
int b = 20;  
CRGB Mycolor(r,g,b);

bool startBrilliant = true; 



// 灯初始化
void LEDinit() {
	FastLED.addLeds<ledType, dataPin, GRB>(led, lightNum);
	FastLED.setBrightness(lightNess);
	fill_solid(led, lightNum,Mycolor);
	FastLED.show();
}



// 色彩模式
void colorMode() {
	Serial.println("colorMode路由请求成功");
	
	Mycolor.r = r; 
	Mycolor.g = g; 
	Mycolor.b = b;
	fill_solid(led, lightNum,Mycolor);
	FastLED.show();

}



//开启灯光控制
void startLEDControl() {
	mode = 0; 
	lightNess = esp8266_server.arg("lightness").toInt();

}



// 开启色彩模式
void startcolorMode() {
	mode = 1;
	Serial.println("colorMode");
	Serial.print(mode);
	r = esp8266_server.arg("r").toInt();
	g = esp8266_server.arg("g").toInt(); 
	b = esp8266_server.arg("b").toInt();
}


// 灯光控制
void LEDControl() {
	Serial.println("LEDControl请求成功");
  FastLED.setBrightness(lightNess);

	esp8266_server.send(200, "text/plain", "Led控制ok");
  mode  = 3;
}

// 没有找到回调
void nofound() {
	esp8266_server.send(400, "text/plain", "错误");
}

void startBrilliantMode() {
	mode = 2; 
	FastLED.addLeds<NEOPIXEL, dataPin>(led, lightNum);
	LEDS.showColor(CRGB(255, 0, 0));
	delay(500);
	LEDS.showColor(CRGB(0, 255, 0));
	delay(500);
	LEDS.showColor(CRGB(0, 0, 255));
	delay(500);
	LEDS.showColor(CRGB(0, 0, 0));
	Serial.begin(115200);
	Serial.println(mode);

}



// 流光溢彩功能
void Brilliant() {
	Serial.println("Brilliant功能开始");
	// Wait for first byte of Magic Word
	for (i = 0; i < sizeof prefix; ++i) {
	waitLoop: while (!Serial.available());;
		// Check next byte in Magic Word
		if (prefix[i] == Serial.read()) continue;
		// otherwise, start over
		i = 0;
		goto waitLoop;
	}

	// Hi, Lo, Checksum  
	while (!Serial.available());;
	hi = Serial.read();
	while (!Serial.available());;
	lo = Serial.read();
	while (!Serial.available());;
	chk = Serial.read();

	// If checksum does not match go back to wait
	if (chk != (hi ^ lo ^ 0x55)) {
		i = 0;
		goto waitLoop;
	}

	memset(led, 0, lightNum * sizeof(struct CRGB));
	// Read the transmission data and set LED values
	for (uint8_t i = 0; i < lightNum; i++) {
		byte r, g, b;
		while (!Serial.available());
		r = Serial.read();
		while (!Serial.available());
		g = Serial.read();
		while (!Serial.available());
		b = Serial.read();
		led[i].r = r;
		led[i].g = g;
		led[i].b = b;
	}

	// Shows new values
	FastLED.show();
}


void rooter() {
	//路由
	esp8266_server.on("/LEDControl", startLEDControl);
	esp8266_server.on("/colorMode", startcolorMode);
	esp8266_server.on("/Brilliant", startBrilliantMode);
	
	esp8266_server.onNotFound(nofound);

}



// wifi 配置
void wifiSetup() {
	WiFi.mode(WIFI_STA);
	WiFi.config(local_IP, gateway, subnet);

	WiFi.softAP(wifiName, wifiPassword);
	wifiMulti.addAP(wifiName, wifiPassword);
	// 开启wifi
	WiFi.begin(wifiName, wifiPassword);

	//开启服务
	esp8266_server.begin();
	Serial.print("ip ----- >");
	Serial.print(WiFi.localIP());
	rooter();

}



//分配功能
void distribute() {
	Serial.println("lightAndcolor 的值 : ");
	Serial.println(mode);
	// 流光溢彩
	if (mode == 2) {  
		Brilliant();
	}
	else if(mode == 0) {
		// LEDinit();
		LEDControl();
  
	}
	else if(mode == 1) {
		// LEDinit();
		colorMode();
	}else if(mode ==3){
      LEDinit();
  }
}



void setup() {
  wifiSetup();
  Serial.print("set up");
  LEDinit();
}

void loop() {
  distribute();
  esp8266_server.handleClient();
}